import curses
import os

from src.constant import project_root_path
from src.util.common_util import while_input, is_multi_file_exist


def __file_selector(stdscr, title="文件选择器", start_path="."):
    # 初始化 curses 颜色
    curses.start_color()
    curses.init_pair(1, curses.COLOR_CYAN, curses.COLOR_BLACK)  # 普通文件（青色）
    curses.init_pair(2, curses.COLOR_YELLOW, curses.COLOR_BLUE)  # 选中项（黄字蓝底）
    curses.init_pair(3, curses.COLOR_GREEN, curses.COLOR_BLACK)  # 目录（绿色）
    curses.init_pair(4, curses.COLOR_RED, curses.COLOR_BLACK)  # 取消选项（红色）
    curses.init_pair(5, curses.COLOR_MAGENTA, curses.COLOR_BLACK)  # 上一级（紫色）
    curses.init_pair(6, curses.COLOR_WHITE, curses.COLOR_GREEN)  # 已选文件（白字绿底）

    curses.curs_set(0)  # 隐藏光标
    stdscr.clear()

    path = os.path.abspath(start_path)  # 设定默认路径
    selected_files = set()  # 记录选中的文件
    selected_file_paths = {}  # 用字典存储文件的绝对路径

    index = 0
    offset = 0  # 记录滚动偏移量

    while True:
        stdscr.clear()
        height, width = stdscr.getmaxyx()  # 获取终端大小
        max_visible = height - 4  # 限制最大可显示文件数（减去标题行）

        # 获取文件列表，先添加 `[..]` 选项返回上一级
        files = ["[..]"] + sorted(os.listdir(path))
        files.append("[取消选择]")  # 添加取消选项

        # 在标题栏显示已选择文件数量
        selected_count = len(selected_files)
        stdscr.addstr(0, 0, f"{title} - 已选择 {selected_count} 个文件",
                      curses.color_pair(1) | curses.A_BOLD | curses.A_UNDERLINE)
        stdscr.addstr(1, 0, f"当前路径: {path}", curses.color_pair(1))

        # 控制滚动
        if index >= offset + max_visible:
            offset += 1
        elif index < offset:
            offset -= 1

        # 显示文件列表（滚动）
        for i in range(min(len(files) - offset, max_visible)):
            file = files[offset + i]
            full_path = os.path.join(path, file)

            if file == "[..]":
                color = curses.color_pair(5)  # 上一级（紫色）
            elif file == "[取消选择]":
                color = curses.color_pair(4)  # 取消（红色）
            elif os.path.isdir(full_path):
                color = curses.color_pair(3)  # 目录（绿色）
            elif os.path.isdir(full_path):  # 目录优先
                color = curses.color_pair(3)  # 目录（绿色）
            elif file in selected_files:
                color = curses.color_pair(6)  # 选中文件（白字绿底）
            else:
                color = curses.color_pair(1)  # 普通文件（青色）

            # 渲染选中状态
            prefix = "[✔] " if file in selected_files else "    "
            if offset + i == index:
                stdscr.addstr(i + 2, 0, f"> {prefix}{file}/" if os.path.isdir(full_path) else f"> {prefix}{file}",
                              curses.color_pair(2) | curses.A_BOLD)
            else:
                stdscr.addstr(i + 2, 0, f"  {prefix}{file}/" if os.path.isdir(full_path) else f"  {prefix}{file}",
                              color)

        key = stdscr.getch()
        if key == curses.KEY_DOWN and index < len(files) - 1:
            index += 1
        elif key == curses.KEY_UP and index > 0:
            index -= 1
        elif key == ord(" "):  # 空格键选中/取消选中
            selected = files[index]
            if selected not in ["[..]", "[取消选择]"] and not os.path.isdir(os.path.join(path, selected)):  # 只允许选中文件
                selected_full_path = os.path.abspath(os.path.join(path, selected))
                if selected_full_path in selected_file_paths:
                    selected_files.remove(selected_full_path)  # 取消选择
                    del selected_file_paths[selected_full_path]  # 移除路径
                else:
                    selected_files.add(selected_full_path)  # 选中文件
                    selected_file_paths[selected_full_path] = selected_full_path  # 存储绝对路径
        elif key == 10:  # 回车键
            selected = files[index]
            if selected == "[取消选择]":
                return None  # 用户取消选择
            elif selected == "[..]":
                parent_path = os.path.dirname(path)  # 获取上一级目录
                if os.path.exists(parent_path):
                    path = parent_path
                    index, offset = 0, 0  # 归零，重新渲染
            elif os.path.isdir(os.path.join(path, selected)):
                path = os.path.join(path, selected)  # 进入目录
                index, offset = 0, 0  # 重新归零
            else:
                # 返回选中文件的绝对路径
                return list(selected_file_paths.values())


def file_selector(title="请选择文件（按空格多选）", start_path=project_root_path):
    return curses.wrapper(__file_selector, title=title, start_path=start_path)


def select_multi_file(use_terminal, title="请选择文件"):
    if use_terminal:
        file_path_list = file_selector(title=title)
        if file_path_list is None:
            return []
    else:
        path = while_input(title, is_multi_file_exist)
        file_path_list = path.split(",")
    return file_path_list
